<?php
/**
 * AnniversaryService.php
 * 文件描述 纪念日逻辑处理中心
 * Created on 2020/8/31 11:48
 * Created by 刘小龙 595929049@qq.com
 */

namespace app\xiangji\services;


use app\common\caches\AnniversaryCache;
use app\common\facades\auth\Auth;
use app\common\models\LoveAchieve;
use app\Request;
use app\common\models\Anniversary;
use app\xiangji\exception\BadRequestException;
use app\xiangji\exception\ModelNotFoundException;
use app\xiangji\jobs\AchieveLoveScoreJob;
use app\xiangji\jobs\GiveLoveScoreJob;
use Carbon\Carbon;
use think\facade\Db;
use think\facade\Queue;

class AnniversaryService
{
    private $anniversaryModel;
    private $user;

    // 内建纪念日，后期数据多了应转数据库储存
    const SYSTEM_BUILT = [
        [
            'union_id'  => '840bfd1cc0eadc16809deea9a0e7bb65',
            'title' => '初识',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => '3f06b37107a5668c82e0f8b1ed4ce77a',
            'title' => '我们在一起的日子',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => 'a13a2a04a5bd22c0cedc0e4bf5160ffe',
            'title' => 'TA的生日',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => '2d18b541992723b4eced0ca6c08401e7',
            'title' => '第一次牵手',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => '50eff345ac9b633a39ad03dfb6f3733c',
            'title' => '第一次亲亲',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => '415d3df4d3cad7b9cfc59aabe608da52',
            'title' => '第一次看电影',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => 'd5d02220abc24f457eac6c12e58decea',
            'title' => '第一次穿情侣装',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => 'c0960a1e43576839a5eedb78cdfa8bd3',
            'title' => '第一次恋爱旅行',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => '58f2952714e5f3313c8df9afe4e75048',
            'title' => '第一次爱爱',
            'type'  => 1,
            'bg_img'    => ''
        ],
        [
            'union_id'  => 'fb75beff30449f6f4e698d5398661a4a',
            'title' => '结婚纪念日',
            'type'  => 1,
            'bg_img'    => ''
        ],
    ];

    public function __construct(Anniversary $anniversary)
    {
        $this->anniversaryModel = $anniversary;
        $this->user = Auth::guard('api')->user();
    }

    /**
     * @todo 查询用户纪念日列表数据
     * @param Request $request
     * @return mixed|\think\Paginator|null
     * @throws \think\db\exception\DbException
     */
    public function search(Request $request)
    {
        $page = $request->get('page', 1);
        $limit = $request->get('limit', 10);
        // 查询用户的内置纪念日
        $system_anns = self::SYSTEM_BUILT;
        $user_sys_anns = $this->user->anniversaries()->whereIn('union_id', array_column($system_anns, 'union_id'))->column('union_id');
        foreach ($system_anns as $k => $v){
            if (in_array($v['union_id'], $user_sys_anns)){
                unset($system_anns[$k]);continue;
            }
            $system_anns[$k]['date'] = null;
            $system_anns[$k]['id'] = $v['union_id'];
            unset($system_anns[$k]['union_id']);
        }

        // 按纪念日时间顺序排序查询
        $data = $this->user->anniversaries()
            ->order('date')
            ->field(['union_id as id', 'title', 'date', 'bg_img', 'type'])
            ->paginate(['list_rows' => $limit, 'page' => $page])->toArray();

        // 最后一页加上未填写得内置纪念日
        if ($data['total'] == 0 || $data['current_page'] == $data['last_page']){
            $data['data'] = array_merge($data['data'], array_values($system_anns));
        }
        return $data;
    }

    /**
     * @todo 获取用户纪念日详情
     * @param $id   纪念日ID
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function show(Request $request)
    {
        $id = $request->get('id', '');
        $user = Auth::guard('api')->user();
        return $user->anniversaries()
            ->where('union_id', '=', $id)
            ->field(['union_id as id', 'title', 'date', 'bg_img', 'type'])
            ->find();
    }

    public function latest()
    {
        $user = Auth::guard('api')->user();
        $today = Carbon::today()->format('Y-m-d');
        $this_year = Carbon::today()->year;
        return $user->anniversaries()
            ->whereFieldRaw(Db::raw("DATE_FORMAT(date, '{$this_year}-%m-%d')"), '>', $today)
            ->order('tdate', 'asc')
            ->field(['union_id as id', 'title', 'date', Db::raw("DATE_FORMAT(date, '{$this_year}-%m-%d') as tdate"), 'bg_img'])
            ->find();
    }

    /**
     * @todo 获取用户最近7天的纪念日信息
     * @return mixed
     */
    public function latestAnniversaries()
    {
        $this_year = Carbon::today()->year;
        $today = Carbon::today()->format('Y-m-d');
        $today_after_7 = Carbon::today()->addDays(7)->format('Y-m-d');
        // 查询缓存数据
        $data = AnniversaryCache::getUserLatestAnniversaries($this->user->id, $today);
        // 无缓存数据读取数据库数据并存入缓存
        if (!$data){
            $sql = <<<EOT
SELECT union_id as id, title, date, bg_img, tdate 
    FROM (
        SELECT *, DATE_FORMAT(date, '{$this_year}-%m-%d') AS tdate 
        FROM xiangji_anniversaries 
        WHERE user_id = {$this->user->id}
    ) a 
    WHERE 
    tdate >= '{$today}' 
    AND 
    tdate <= '{$today_after_7}' 
    ORDER BY tdate
EOT;
            $data = Db::query($sql);
            AnniversaryCache::setUserLatestAnniversaries($this->user->id, $today, $data);
        }
        return $data;
    }

    /**
     * @todo 新增保存用户纪念日信息
     * @param Request $request
     * @return mixed
     */
    public function store(Request $request)
    {
        $data = $request->post(['title', 'date', 'bg_img']);
        $data['type'] = 2; // 用户自定义
        $data['union_id'] = md5(microtime(true));
        $is_safe_content = (new WechatService())->checkText($data['title']);
        if ($is_safe_content['errcode'] != 0){
            throw new BadRequestException('内容含有违法违规内容');
        }
        $anniversary = $this->user->anniversaries()->save($data);
        // 发放奖励
        Queue::push(GiveLoveScoreJob::class, ['user_id' => $this->user->id, 'score' => 2, 'scene' => '新增纪念日奖励'], 'give_love_score');
        // 触发成就
        Queue::push(AchieveLoveScoreJob::class, ['user_id' => $this->user->id, 'type' => LoveAchieve::TYPE_ANNIVERSARY], 'love_score_achieve');
        return $anniversary;
    }

    /**
     * @todo 更新用户纪念日信息
     * @param Request $request
     * @param $id   纪念日ID
     * @return bool
     * @throws ModelNotFoundException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function update(Request $request)
    {
        $data = $request->put(['id', 'type', 'title', 'date', 'bg_img']);
        $anniversary = $this->user->anniversaries()->where('union_id', '=', $data['id'])->find();
        $is_sys_ann = in_array($data['id'], array_column(self::SYSTEM_BUILT, 'union_id'));
        // 如果未在用户纪念日数据库中找到
        if (!$anniversary){
            // 且也不是内置纪念日则提示未找到
            if (!$is_sys_ann){
                throw new ModelNotFoundException('未找到该纪念日信息');
            }else{
                // 未填写的内置纪念日，则新增
                $data['union_id'] = $data['id'];
                $data['type'] = 1;  // 系统内置
                unset($data['id']);
                // 新增
                $this->user->anniversaries()->save(array_merge($data, ['template_id' => $request->put('id')]));
                // 发放恩爱值
                Queue::push(GiveLoveScoreJob::class, ['user_id' => $this->user->id, 'score' => 2, 'scene' => '新增纪念日奖励'], 'give_love_score');
                // 触发成就
                Queue::push(AchieveLoveScoreJob::class, ['user_id' => $this->user->id, 'type' => LoveAchieve::TYPE_ANNIVERSARY], 'love_score_achieve');
                return true;
            }
        }
        // 非系统内置需要检测内容安全
        if (!$is_sys_ann){
            $is_safe_content = (new WechatService())->checkText($data['title']);
            if ($is_safe_content['errcode'] != 0){
                throw new BadRequestException('内容含有违法违规内容');
            }
        }
        unset($data['id']);
        return $anniversary->save(!$is_sys_ann ? $data : $request->put(['date', 'bg_img']));
    }

    /**
     * @todo 删除用户纪念日：软删除
     * @param $id   纪念日ID
     * @return bool
     * @throws ModelNotFoundException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function del($id)
    {
        // 判断该纪念日是否存在
        $anniversary = $this->user->anniversaries()->where('type', '=', 2)->where('union_id', '=', $id)->find();
        if (!$anniversary){
            throw new ModelNotFoundException('未找到该纪念日信息');
        }
        AnniversaryCache::flushUserAnniversaryData($this->user->id);  // 清空缓存
        // 软删除该纪念日
        return $anniversary->delete();
    }
}
